package com.atguigu.gmall.order.receiver;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.model.payment.PaymentInfo;
import com.atguigu.gmall.order.service.OrderInfoService;
import com.atguigu.gmall.payment.client.PaymentFeignClient;
import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import springfox.documentation.spring.web.json.Json;

import java.util.Map;

/**
 * @Author: zm
 * @Date: 2021/8/26 16:27
 */
@Component
public class OrderReceiver {

    @Autowired
    private OrderInfoService orderInfoService;

    @Autowired
    private PaymentFeignClient paymentFeignClient;

    @SneakyThrows
    @RabbitListener(queues = MqConst.QUEUE_ORDER_CANCEL)
    public void cancelOrder(Long orderInfoId, Message message, Channel channel) {
        //  发过来的是订单Id，那么你就需要判断一下当前的订单是否已经支付了。
        //  未支付的情况下：关闭订单
        //  根据订单Id 查询orderInfo select * from order_info where id = orderId
        //  利用这个接口IService  实现类ServiceImpl 完成根据订单Id 查询订单信息 ServiceImpl 类底层还是使用的mapper
        if (orderInfoId == null) {
            return;
        }
        try {
            OrderInfo orderInfo = orderInfoService.getById(orderInfoId);
            // 判断订单状态
            if (orderInfo != null && "UNPAID".equals(orderInfo.getOrderStatus()) && "UNPAID".equals(orderInfo.getProcessStatus())) {
                PaymentInfo paymentInfo = paymentFeignClient.getPaymentInfo(orderInfo.getOutTradeNo());
                // 判断是否产生交易记录
                if (paymentInfo != null && "UNPAID".equals(paymentInfo.getPaymentStatus())) {
                    // 有交易记录 判断是否和支付宝产生交易记录
                    Boolean checkPayment = paymentFeignClient.checkPayment(orderInfoId);

                    if (checkPayment) {
                        // 与支付宝产生交易交易记录  看是否已支付  未支付可以关闭
                        Boolean closeTrade = paymentFeignClient.closeTrade(orderInfoId);
                        if (closeTrade) {
                            // 支付宝交易交流已关闭  关闭本地订单 和 本地交易记录
                            orderInfoService.execExpiredOrder(orderInfoId, "2");
                        } else {
                            // 已经有支付成功走异步回调了
                        }
                    } else {
                        // 未与支付宝产出交易记录, 直接关闭本地订单和本地交易记录
                        orderInfoService.execExpiredOrder(orderInfoId, "2");
                    }
                } else {
                    // 关闭订单  未产生交易记录 只关闭订单
                    orderInfoService.execExpiredOrder(orderInfoId, "1");
                }
            }
        } catch (Exception e) {
            // 记录日志  或 将无法正常处理的 数据 放到数据表中
            e.printStackTrace();
        }
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }

    // 订单支付成功,更新订单状态  rabbitmq发送信息给库存系统
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_PAYMENT_PAY, durable = "true", autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_PAYMENT_PAY),
            key = {MqConst.ROUTING_PAYMENT_PAY}
    ))
    public void updateOrderStatus(Long orderId, Message message, Channel channel) {
        try {
            if (orderId != null) {
                // 更新订单状态为已支付
                OrderInfo orderInfo = orderInfoService.getById(orderId);

                if ("UNPAID".equals(orderInfo.getOrderStatus())) {
                    orderInfoService.updateOrderStatus(orderId, ProcessStatus.PAID);
                    // 调用 方法给库存信息发信息
                    orderInfoService.sendOrderStatus(orderId);
                }
            }
        } catch (Exception e) {
            // 日志记录，将数据写入数据库，做消息补偿.....
            e.printStackTrace();
        }
        // 手动确认消息
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }


    // {"orderId":"230","status":"DEDUCTED"}
    // 监听库存状态并更新订单状态
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_WARE_ORDER, durable = "true", autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_WARE_ORDER),
            key = {MqConst.ROUTING_WARE_ORDER}
    ))
    public void updateOrder(String str, Message message, Channel channel) {
        try {
            if (!StringUtils.isEmpty(str)) {
                Map map = JSON.parseObject(str, Map.class);
                String orderId = (String) map.get("orderId");
                String status = (String) map.get("status");

                if ("DEDUCTED".equals(status)) { // 已减库存
                    orderInfoService.updateOrderStatus(Long.parseLong(orderId), ProcessStatus.WAITING_DELEVER);
                } else {
                    //  出现了库存异常：有可能是超卖！
                    //  记录信息： orderId ,放入一个表中进行存储！ 远程补货！ 再次发送一个消息：更新当前的减库存状态! 数据的最终一致性！
                    //  分布式事务：解决方案！
                    //  亲，小哥哥你等会。我们正在补货！ 人工客服！ 退款！
                    orderInfoService.updateOrderStatus(Long.parseLong(orderId), ProcessStatus.STOCK_EXCEPTION);
                }
            }
        } catch (Exception e) {
            // 记录日志
            e.printStackTrace();
        }

        // 手动确认消息
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);

    }

}
